





<!DOCTYPE html>
<html class="writer-html5" lang="zh-CN" >
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>Pattern Matching in Relay &mdash; tvm 0.8.dev1982 文档</title>
  

  
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/gallery.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/css/tlcpack_theme.css" type="text/css" />

  
  
    <link rel="shortcut icon" href="../../_static/tvm-logo-square.png"/>
  

  
  
  
  
    
      <script type="text/javascript" id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
        <script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
        <script src="../../_static/jquery.js"></script>
        <script src="../../_static/underscore.js"></script>
        <script src="../../_static/doctools.js"></script>
        <script src="../../_static/translations.js"></script>
    
    <script type="text/javascript" src="../../_static/js/theme.js"></script>

    
    <script type="text/javascript" src="../../_static/js/tlcpack_theme.js"></script>
    <link rel="index" title="索引" href="../../genindex.html" />
    <link rel="search" title="搜索" href="../../search.html" />
    <link rel="next" title="Hybrid Frontend Language Reference" href="hybrid_script.html" />
    <link rel="prev" title="Relay 基础张量算子" href="relay_op.html" /> 
</head>

<body class="wy-body-for-nav">

   
  <div class="wy-grid-for-nav">
    
    
<header class="header">
    <div class="innercontainer">
      <div class="headerInner d-flex justify-content-between align-items-center">
          <div class="headerLogo">
               <a href="https://tvm.apache.org/"><img src=https://tvm.apache.org/assets/images/logo.svg alt="logo"></a>
          </div>

          <div id="headMenu" class="headerNav">
            <button type="button" id="closeHeadMenu" class="navCloseBtn"><img src="../../_static/img/close-icon.svg" alt="Close"></button>
             <ul class="nav">
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/community>Community</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/download>Download</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/vta>VTA</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/blog>Blog</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/docs>Docs</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvmconf.org>Conference</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://github.com/apache/tvm/>Github</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvmchinese.github.io/declaration_zh_CN.html>About-Translators</a>
                </li>
             </ul>
               <div class="responsivetlcdropdown">
                 <button type="button" class="btn-link">
                   ASF
                 </button>
                 <ul>
                     <li>
                       <a href=https://apache.org/>Apache Homepage</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/licenses/>License</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/security/>Security</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/thanks.html>Thanks</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/events/current-event>Events</a>
                     </li>
                     <li>
                       <a href=https://www.zhihu.com/column/c_1429578595417563136>Zhihu</a>
                     </li>
                 </ul>
               </div>
          </div>
            <div class="responsiveMenuIcon">
              <button type="button" id="menuBtn" class="btn-menu"><img src="../../_static/img/menu-icon.svg" alt="Menu Icon"></button>
            </div>

            <div class="tlcDropdown">
              <div class="dropdown">
                <button type="button" class="btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  ASF
                </button>
                <div class="dropdown-menu dropdown-menu-right">
                  <ul>
                     <li>
                       <a href=https://apache.org/>Apache Homepage</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/licenses/>License</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/security/>Security</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/thanks.html>Thanks</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/events/current-event>Events</a>
                     </li>
                     <li>
                       <a href=https://www.zhihu.com/column/c_1429578595417563136>Zhihu</a>
                     </li>
                  </ul>
                </div>
              </div>
          </div>
       </div>
    </div>
 </header>
 
    <nav data-toggle="wy-nav-shift" class="wy-nav-side fixed">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >
          

          
            <a href="../../index.html">
          

          
            
            <img src="../../_static/tvm-logo-small.png" class="logo" alt="Logo"/>
          
          </a>

          
            
            
                <div class="version">
                  0.8.dev1982
                </div>
            
          

          
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>

          
        </div>

        
        <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
          
            
            
              
            
            
              <p class="caption" role="heading"><span class="caption-text">如何开始</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../install/index.html">安装 TVM</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../contribute/index.html">贡献者指南</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">用户引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../tutorial/index.html">User Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../how_to/index.html">How To Guides</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">开发者引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../dev/tutorial/index.html">Developer Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev/how_to/how_to.html">开发者指南</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">架构指南</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../arch/index.html">Design and Architecture</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">主题引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../topic/microtvm/index.html">microTVM：裸机使用TVM</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../topic/vta/index.html">VTA: Versatile Tensor Accelerator</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">参考指南</span></p>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="index.html">语言参考</a><ul class="current">
<li class="toctree-l2 current"><a class="reference internal" href="index.html#introduction-to-relay">Relay简介</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="relay_expr.html">Expressions in Relay</a></li>
<li class="toctree-l3"><a class="reference internal" href="relay_type.html">Relay 系统类型</a></li>
<li class="toctree-l3"><a class="reference internal" href="relay_adt.html">Algebraic Data Types in Relay</a></li>
<li class="toctree-l3"><a class="reference internal" href="relay_op.html">Relay 基础张量算子</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Pattern Matching in Relay</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#pattern-examples">Pattern Examples</a></li>
<li class="toctree-l4"><a class="reference internal" href="#matching-fuzzy-patterns">Matching Fuzzy Patterns</a></li>
<li class="toctree-l4"><a class="reference internal" href="#pattern-language-design">Pattern Language Design</a></li>
<li class="toctree-l4"><a class="reference internal" href="#applications">Applications</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="index.html#hybrid-script">混合式脚本</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../api/python/index.html">Python API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/links.html">Other APIs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../publications.html">Publications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../genindex.html">索引</a></li>
</ul>

            
          
        </div>
        
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
      
      <nav class="wy-nav-top" aria-label="top navigation" data-toggle="wy-nav-top">
        
            <div class="togglemenu">

            </div>
            <div class="nav-content">
              <!-- tvm -->
              Table of content
            </div>
        
      </nav>


      <div class="wy-nav-content">
        
        <div class="rst-content">
        

          




















<div role="navigation" aria-label="breadcrumbs navigation">

  <ul class="wy-breadcrumbs">
    
      <li><a href="../../index.html">Docs</a> <span class="br-arrow">></span></li>
        
          <li><a href="index.html">语言参考</a> <span class="br-arrow">></span></li>
        
      <li>Pattern Matching in Relay</li>
    
    
      <li class="wy-breadcrumbs-aside">
        
            
            <a href="../../_sources/reference/langref/relay_pattern.rst.txt" rel="nofollow"> <img src="../../_static//img/source.svg" alt="viewsource"/></a>
          
        
      </li>
    
  </ul>

  
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
            
  <div class="section" id="pattern-matching-in-relay">
<h1>Pattern Matching in Relay<a class="headerlink" href="#pattern-matching-in-relay" title="永久链接至标题">¶</a></h1>
<p>There are many places in TVM where we identify pure data-flow sub-graphs of the Relay program and attempt to transform them in some way example passes include fusion, quantization, external code generation, and device specific optimizations such as bitpacking, and layer slicing used by VTA.</p>
<p>Many of these passes today require a lots of boring boilerplate code in order to implement as well as requiring users to think in terms of visitors and AST matching. Many of these transformations can easily be described in terms of graph rewrites. In order to build a rewriter or other advanced machinery we first need a language of patterns to describe what we can match.</p>
<p>Such a language is not just useful for building a rewriter but also providing extension points for existing passes. For example the fusion pass could be parameterized by a set of fusion patterns which describes the capability of your hardware, and the quantization pass could take a set of patterns which describe which operators can be quantized on a given platform.</p>
<p>In the backend world, we could use the same machinery to build a higher level API using bring your own code generation. This API takes set of patterns describing your hardware capabilities and an external compiler, providing a relatively smooth heterogeneous experience out of the box.</p>
<div class="section" id="pattern-examples">
<h2>Pattern Examples<a class="headerlink" href="#pattern-examples" title="永久链接至标题">¶</a></h2>
<p>There are quite a few properties of operators that are worth matching. Below we examine how to match tree properties, and expand on some use cases that are not fully explored in the prototype. This section
demonstrates how to write patterns. It is recommended to check <a class="reference external" href="https://github.com/apache/tvm/blob/main/tests/python/relay/test_dataflow_pattern.py">tests/python/relay/test_dataflow_pattern.py</a>
for more use cases.</p>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>If you cannot find the corresponding pattern node to match the Relay node you want,
you are welcome to raise an issue or submit a PR to add it.</p>
</div>
<div class="section" id="matching-one-of-two-ops">
<h3>Matching One of Two Ops<a class="headerlink" href="#matching-one-of-two-ops" title="永久链接至标题">¶</a></h3>
<p>The first example is a simple case where we want to match one operator with a single input OR
another operator with a single input:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_op_or</span><span class="p">():</span>
    <span class="n">is_add_or_sub</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;add&#39;</span><span class="p">)</span> <span class="o">|</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;subtract&#39;</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">is_add_or_sub</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;add&quot;</span><span class="p">))</span>
    <span class="k">assert</span> <span class="n">is_add_or_sub</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;subtract&quot;</span><span class="p">))</span>
</pre></div>
</div>
</div>
<div class="section" id="matching-an-op-with-attributes">
<h3>Matching an Op with Attributes<a class="headerlink" href="#matching-an-op-with-attributes" title="永久链接至标题">¶</a></h3>
<p>The next example is a dense operation with any operator that is marked element-wise:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_no_match_attr</span><span class="p">():</span>
    <span class="n">op</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.dense&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">has_attr</span><span class="p">({</span><span class="s2">&quot;TOpPattern&quot;</span><span class="p">:</span> <span class="n">K_ELEMWISE</span><span class="p">})</span>
    <span class="n">op_pat</span> <span class="o">=</span> <span class="n">op</span><span class="p">(</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">())</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;y&#39;</span><span class="p">)</span>
    <span class="k">assert</span> <span class="ow">not</span> <span class="n">op_pat</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">dense</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
</pre></div>
</div>
<p>Here is another example to match an op with a specific attribute:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_data_layout</span><span class="p">():</span>
    <span class="n">is_conv2d</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.conv2d&#39;</span><span class="p">)(</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">())</span><span class="o">.</span><span class="n">has_attr</span><span class="p">({</span><span class="s2">&quot;data_layout&quot;</span><span class="p">:</span> <span class="s2">&quot;NHWC&quot;</span><span class="p">})</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;y&#39;</span><span class="p">)</span>
    <span class="k">assert</span> <span class="ow">not</span> <span class="n">is_conv2d</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">conv2d</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
</pre></div>
</div>
<p>Or a convolution with a specific kernel size:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_kernel_size</span><span class="p">():</span>
    <span class="n">is_conv2d</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s2">&quot;nn.conv2d&quot;</span><span class="p">)(</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">())</span><span class="o">.</span><span class="n">has_attr</span><span class="p">({</span><span class="s2">&quot;kernel_size&quot;</span><span class="p">:</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">]})</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;y&#39;</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">is_conv2d</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">conv2d</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">kernel_size</span><span class="o">=</span><span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">]))</span>
</pre></div>
</div>
</div>
<div class="section" id="matching-an-optional-op">
<h3>Matching an Optional Op<a class="headerlink" href="#matching-an-optional-op" title="永久链接至标题">¶</a></h3>
<p>The next example is matching a pattern with one optional operator. In this pattern,
we can match the graph of conv2d+bias_add+relu or the graph of conv2d+bias_add.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_optional</span><span class="p">():</span>
    <span class="n">conv_node</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.conv2d&#39;</span><span class="p">)(</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">())</span>
    <span class="n">bias_node</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.bias_add&#39;</span><span class="p">)(</span><span class="n">conv_node</span><span class="p">,</span> <span class="n">wildcard</span><span class="p">())</span>
    <span class="n">pat</span> <span class="o">=</span> <span class="n">bias_node</span><span class="o">.</span><span class="n">optional</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.relu&#39;</span><span class="p">)(</span><span class="n">x</span><span class="p">))</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;y&#39;</span><span class="p">)</span>
    <span class="n">z</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;z&#39;</span><span class="p">)</span>
    <span class="n">conv2d</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">conv2d</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
    <span class="n">bias</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">bias_add</span><span class="p">(</span><span class="n">conv2d</span><span class="p">,</span> <span class="n">z</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">pat</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">bias</span><span class="p">)</span>
    <span class="n">relu</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">relu</span><span class="p">(</span><span class="n">bias</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">pat</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relu</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="matching-types">
<h3>Matching Types<a class="headerlink" href="#matching-types" title="永久链接至标题">¶</a></h3>
<p>In addition to matching ops with attributes, we can also make a pattern to match their types, in interms of the shape and data type. Here are some examples:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_type</span><span class="p">():</span>
    <span class="c1"># Match any op with float32</span>
    <span class="n">pat1</span> <span class="o">=</span> <span class="n">has_dtype</span><span class="p">(</span><span class="s1">&#39;float32&#39;</span><span class="p">)</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="n">dtype</span><span class="o">=</span><span class="s1">&#39;float32&#39;</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">pat1</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>

    <span class="c1"># Match any op with shape (10, 10)</span>
    <span class="n">pat2</span> <span class="o">=</span> <span class="n">has_shape</span><span class="p">((</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="n">dtype</span><span class="o">=</span><span class="s1">&#39;float32&#39;</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">pat2</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>

    <span class="c1"># Match conv2d+relu with a certain shape</span>
    <span class="n">conv2d</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.conv2d&#39;</span><span class="p">)(</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">())</span>
    <span class="n">pat3</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.relu&#39;</span><span class="p">)(</span><span class="n">conv2d</span><span class="p">)</span><span class="o">.</span><span class="n">has_shape</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">28</span><span class="p">,</span> <span class="mi">28</span><span class="p">))</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">28</span><span class="p">,</span> <span class="mi">28</span><span class="p">),</span> <span class="n">dtype</span><span class="o">=</span><span class="s1">&#39;float32&#39;</span><span class="p">)</span>
    <span class="n">w</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;w&#39;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">32</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="n">dtype</span><span class="o">=</span><span class="s1">&#39;float32&#39;</span><span class="p">)</span>
    <span class="n">conv2d</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">conv2d</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">w</span><span class="p">,</span> <span class="n">strides</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">padding</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
    <span class="n">relu</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">relu</span><span class="p">(</span><span class="n">conv2d</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">pat3</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relu</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="matching-non-call-nodes">
<h3>Matching Non-Call Nodes<a class="headerlink" href="#matching-non-call-nodes" title="永久链接至标题">¶</a></h3>
<p>Sometimes we may also want to match a pattern that includes Tuple or TupleGetItem nodes.
Since there are not call nodes, we need to use specific pattern nodes to match them:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_tuple</span><span class="p">():</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;y&#39;</span><span class="p">)</span>
    <span class="n">z</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;z&#39;</span><span class="p">)</span>
    <span class="n">tuple_pattern</span> <span class="o">=</span> <span class="n">is_tuple</span><span class="p">((</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">()))</span>
    <span class="k">assert</span> <span class="n">tuple_pattern</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">expr</span><span class="o">.</span><span class="n">Tuple</span><span class="p">((</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">,</span><span class="n">z</span><span class="p">)))</span>
</pre></div>
</div>
<p>The next example is matching a pattern of batch_norm -&gt; get(0) -&gt; relu. Note that you can also use <cite>is_tuple_get_item(bn_node)</cite> to match a <cite>TupleGetItem</cite> node with any index.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_tuple_get_item</span><span class="p">():</span>
    <span class="n">bn_node</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.batch_norm&#39;</span><span class="p">)(</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">())</span>
    <span class="n">tuple_get_item_node</span> <span class="o">=</span> <span class="n">is_tuple_get_item</span><span class="p">(</span><span class="n">bn_node</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
    <span class="n">pat</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.relu&#39;</span><span class="p">)(</span><span class="n">tuple_get_item_node</span><span class="p">)</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span>
    <span class="n">gamma</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;gamma&quot;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">8</span><span class="p">,))</span>
    <span class="n">beta</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;beta&quot;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">8</span><span class="p">,))</span>
    <span class="n">moving_mean</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;moving_mean&quot;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">8</span><span class="p">,))</span>
    <span class="n">moving_var</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;moving_var&quot;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">8</span><span class="p">,))</span>
    <span class="n">bn_node</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">batch_norm</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">gamma</span><span class="p">,</span> <span class="n">beta</span><span class="p">,</span> <span class="n">moving_mean</span><span class="p">,</span> <span class="n">moving_var</span><span class="p">)</span>
    <span class="n">tuple_get_item_node</span> <span class="o">=</span> <span class="n">bn_node</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
    <span class="n">out</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">relu</span><span class="p">(</span><span class="n">tuple_get_item_node</span><span class="p">)</span>
    <span class="n">pat</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
</pre></div>
</div>
<p>If we have a pattern that crosses a function boundary, we might want to match the Function itself</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_func</span><span class="p">():</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;x&quot;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;y&quot;</span><span class="p">)</span>
    <span class="n">wc1</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span>
    <span class="n">wc2</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span>
    <span class="n">func_pattern</span> <span class="o">=</span> <span class="n">FunctionPattern</span><span class="p">([</span><span class="n">wc1</span><span class="p">,</span> <span class="n">wc2</span><span class="p">],</span> <span class="n">wc1</span> <span class="o">+</span> <span class="n">wc2</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">func_pattern</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">Function</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">],</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">))</span>
</pre></div>
</div>
<p>The next example is matching a constant node regarding its values. This is useful to check
if a specific parameter in a subgraph has been bound or not.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_constant</span><span class="p">():</span>
    <span class="n">conv2d</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.conv2d&#39;</span><span class="p">)(</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">is_constant</span><span class="p">())</span>
    <span class="n">pattern</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.bias_add&#39;</span><span class="p">)(</span><span class="n">conv2d</span><span class="p">,</span> <span class="n">wildcard</span><span class="p">())</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">224</span><span class="p">,</span> <span class="mi">224</span><span class="p">))</span>
    <span class="n">w</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;w&#39;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
    <span class="n">b</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;b&#39;</span><span class="p">,</span> <span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="p">))</span>
    <span class="n">conv2d</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">conv2d</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">w</span><span class="p">)</span>
    <span class="n">out</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">bias_add</span><span class="p">(</span><span class="n">conv2d</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
    <span class="n">func</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">Function</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">w</span><span class="p">,</span> <span class="n">b</span><span class="p">],</span> <span class="n">out</span><span class="p">)</span>
    <span class="n">mod</span> <span class="o">=</span> <span class="n">tvm</span><span class="o">.</span><span class="n">IRModule</span><span class="o">.</span><span class="n">from_expr</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>

    <span class="c1"># Two inputs of the conv2d in the graph are VarNode by default, so no match.</span>
    <span class="k">assert</span> <span class="ow">not</span> <span class="n">pattern</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">mod</span><span class="p">[</span><span class="s1">&#39;main&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">body</span><span class="p">)</span>

    <span class="c1"># The second input (weight) has been bind with constant values so it is now a constant node.</span>
    <span class="n">mod</span><span class="p">[</span><span class="s2">&quot;main&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">bind_params_by_name</span><span class="p">(</span><span class="n">mod</span><span class="p">[</span><span class="s2">&quot;main&quot;</span><span class="p">],</span>
                                    <span class="p">{</span><span class="s1">&#39;w&#39;</span><span class="p">:</span> <span class="n">tvm</span><span class="o">.</span><span class="n">nd</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">ones</span><span class="p">(</span><span class="n">shape</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">)))})</span>
    <span class="k">assert</span> <span class="n">pattern</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">mod</span><span class="p">[</span><span class="s1">&#39;main&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">body</span><span class="p">)</span>
</pre></div>
</div>
<p>On the other hand, if you need to match the constant with a specific value, you can directly
use <code class="docutils literal notranslate"><span class="pre">is_expr</span></code>. This could be useful for algebraic simplify.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_plus_zero</span><span class="p">():</span>
    <span class="n">zero</span> <span class="o">=</span> <span class="p">(</span><span class="n">is_expr</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">const</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span> <span class="o">|</span> <span class="n">is_expr</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">const</span><span class="p">(</span><span class="mf">0.0</span><span class="p">)))</span>
    <span class="n">pattern</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span> <span class="o">+</span> <span class="n">zero</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">Var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">relay</span><span class="o">.</span><span class="n">const</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">pattern</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">y</span><span class="p">)</span>
</pre></div>
</div>
<p>The next example is matching function nodes with a specific attribute:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_function</span><span class="p">():</span>
    <span class="n">pattern</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span><span class="o">.</span><span class="n">has_attr</span><span class="p">({</span><span class="s2">&quot;Composite&quot;</span><span class="p">:</span> <span class="s2">&quot;add&quot;</span><span class="p">})</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;y&#39;</span><span class="p">)</span>
    <span class="n">f</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">Function</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">],</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">)</span><span class="o">.</span><span class="n">with_attr</span><span class="p">(</span><span class="s2">&quot;Composite&quot;</span><span class="p">,</span> <span class="s2">&quot;add&quot;</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">pattern</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</pre></div>
</div>
<p>A Relay <code class="docutils literal notranslate"><span class="pre">If</span></code> expression can be matched if all of its condition, true branch and false branch
are matched:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_if</span><span class="p">():</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">is_var</span><span class="p">(</span><span class="s2">&quot;x&quot;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">is_var</span><span class="p">(</span><span class="s2">&quot;y&quot;</span><span class="p">)</span>
    <span class="n">pat</span> <span class="o">=</span> <span class="n">is_if</span><span class="p">(</span><span class="n">is_op</span><span class="p">(</span><span class="s2">&quot;less&quot;</span><span class="p">)(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;x&quot;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;y&quot;</span><span class="p">)</span>
    <span class="n">cond</span> <span class="o">=</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span>

    <span class="k">assert</span> <span class="n">pat</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">expr</span><span class="o">.</span><span class="n">If</span><span class="p">(</span><span class="n">cond</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
</pre></div>
</div>
<p>A Relay <code class="docutils literal notranslate"><span class="pre">Let</span></code> expression can be matched if all of its variable, value, and body
are matched:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_let</span><span class="p">():</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">is_var</span><span class="p">(</span><span class="s2">&quot;x&quot;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">is_var</span><span class="p">(</span><span class="s2">&quot;y&quot;</span><span class="p">)</span>
    <span class="n">let_var</span> <span class="o">=</span> <span class="n">is_var</span><span class="p">(</span><span class="s2">&quot;let&quot;</span><span class="p">)</span>
    <span class="n">pat</span> <span class="o">=</span> <span class="n">is_let</span><span class="p">(</span><span class="n">let_var</span><span class="p">,</span> <span class="n">is_op</span><span class="p">(</span><span class="s2">&quot;less&quot;</span><span class="p">)(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="n">let_var</span><span class="p">)</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;x&quot;</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;y&quot;</span><span class="p">)</span>
    <span class="n">lv</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s2">&quot;let&quot;</span><span class="p">)</span>
    <span class="n">cond</span> <span class="o">=</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span>
    <span class="k">assert</span> <span class="n">pat</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">relay</span><span class="o">.</span><span class="n">expr</span><span class="o">.</span><span class="n">Let</span><span class="p">(</span><span class="n">lv</span><span class="p">,</span> <span class="n">cond</span><span class="p">,</span> <span class="n">lv</span><span class="p">))</span>
</pre></div>
</div>
</div>
<div class="section" id="matching-diamonds-and-post-dominator-graphs">
<h3>Matching Diamonds and Post-Dominator Graphs<a class="headerlink" href="#matching-diamonds-and-post-dominator-graphs" title="永久链接至标题">¶</a></h3>
<p>The next example is matching a diamond with two inputs at the top of the diamond:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_diamond</span><span class="p">():</span>
    <span class="c1"># Pattern</span>
    <span class="n">is_conv2d</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.conv2d&#39;</span><span class="p">)(</span><span class="n">is_var</span><span class="p">(),</span> <span class="n">is_var</span><span class="p">())</span>
    <span class="n">path1</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.relu&#39;</span><span class="p">)(</span><span class="n">is_conv2d</span><span class="p">)</span>
    <span class="n">path2</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.leaky_relu&#39;</span><span class="p">)(</span><span class="n">is_conv2d</span><span class="p">)</span>
    <span class="n">diamond</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;add&#39;</span><span class="p">)(</span><span class="n">path1</span><span class="p">,</span> <span class="n">path2</span><span class="p">)</span>

    <span class="c1"># Expr</span>
    <span class="n">inp</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;input&#39;</span><span class="p">)</span>
    <span class="n">weight</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;weight&#39;</span><span class="p">)</span>
    <span class="n">conv2d</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">conv2d</span><span class="p">(</span><span class="n">inp</span><span class="p">,</span> <span class="n">weight</span><span class="p">)</span>
    <span class="n">relu</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">relu</span><span class="p">(</span><span class="n">conv2d</span><span class="p">)</span>
    <span class="n">leaky_relu</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">leaky_relu</span><span class="p">(</span><span class="n">conv2d</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
    <span class="n">out</span> <span class="o">=</span> <span class="n">relu</span> <span class="o">+</span> <span class="n">leaky_relu</span>

    <span class="c1"># Check</span>
    <span class="k">assert</span> <span class="n">diamond</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
</pre></div>
</div>
<p>The final example is matching diamonds with a post-dominator relationship. We embed dominator analysis as type of matching in the pattern language in order to allow for pattern matching with unknown topology. This is important because we want to be able to use the language to describe fuse patterns, like elementwise operations followed by a conv2d:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_match_dom_diamond</span><span class="p">():</span>
    <span class="c1"># Pattern</span>
    <span class="n">is_conv2d</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;nn.conv2d&#39;</span><span class="p">)(</span><span class="n">is_var</span><span class="p">(),</span> <span class="n">is_var</span><span class="p">())</span>
    <span class="n">reduction</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s1">&#39;add&#39;</span><span class="p">)(</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">())</span>
    <span class="n">diamond</span> <span class="o">=</span> <span class="n">dominates</span><span class="p">(</span><span class="n">is_conv2d</span><span class="p">,</span> <span class="n">is_elemwise</span><span class="p">,</span> <span class="n">reduction</span><span class="p">)</span>

    <span class="c1"># Expr</span>
    <span class="n">inp</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;input&#39;</span><span class="p">)</span>
    <span class="n">weight</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;weight&#39;</span><span class="p">)</span>
    <span class="n">conv2d</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">conv2d</span><span class="p">(</span><span class="n">inp</span><span class="p">,</span> <span class="n">weight</span><span class="p">)</span>
    <span class="n">relu</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">relu</span><span class="p">(</span><span class="n">conv2d</span><span class="p">)</span>
    <span class="n">leaky_relu</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">leaky_relu</span><span class="p">(</span><span class="n">conv2d</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
    <span class="n">out</span> <span class="o">=</span> <span class="n">relu</span> <span class="o">+</span> <span class="n">leaky_relu</span>

    <span class="c1"># Check</span>
    <span class="k">assert</span> <span class="n">diamond</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="matching-fuzzy-patterns">
<h2>Matching Fuzzy Patterns<a class="headerlink" href="#matching-fuzzy-patterns" title="永久链接至标题">¶</a></h2>
<p>The Dominator analysis above lets one match a subgraph of Relay AST that doesn’t correspond to a set of patterns nodes exactly 1-to-1. There are a few other places where we support such “fuzzy” matching.</p>
<p>Tuples, Functions, and Call nodes with any number of inputs can be matched by passing <cite>None</cite> as the argument value, i.e.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tuple_pattern</span> <span class="o">=</span> <span class="n">is_tuple</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
<span class="n">func_pattern</span> <span class="o">=</span> <span class="n">FunctionPattern</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">wildcard</span><span class="p">()</span> <span class="o">+</span> <span class="n">wildcard</span><span class="p">())</span>
<span class="n">call_pattern</span> <span class="o">=</span> <span class="n">func_pattern</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
</pre></div>
</div>
<p>These patterns allow matching more generic classes patterns by constraining the use of the arguments rather than the number of arguments.</p>
<p>Additionally, we support matching Functions with fuzzy bodies, i.e., a function body that is under constrained by the pattern. The pattern <cite>FunctionPattern([is_var(), is_var()], wildcard() + wildcard()])</cite> will match <cite>relay.Function([x, y], x + y)</cite>, but it will also match <cite>relay.Function([x, y], x * x + y)</cite>. In the second case, the pattern doesn’t perfectly constrain the body of the function, so the resulting match is fuzzy.</p>
</div>
<div class="section" id="pattern-language-design">
<h2>Pattern Language Design<a class="headerlink" href="#pattern-language-design" title="永久链接至标题">¶</a></h2>
<p>The pattern language proposed is designed to be a mirror of Relay’s IR with additional support for common scenarios. The goal of the pattern language is to provide a regular-expression like capability for matching data-flow graphs and doing rewriting.</p>
<p>The high level design is to introduce a language of patterns for now we propose the language as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Pattern ::= expr
        | *
        | pattern(pattern1, ... patternN)
        | has_type(type)
        | has_dtype(type)
        | has_shape(shape)
        | has_attr(attrs)
        | is_var(name)
        | is_constant()
        | is_expr(expr)
        | is_op(op_name)
        | is_tuple()
        | is_tuple_get_item(pattern, index = None)
        | is_if(cond, tru, fls)
        | is_let(var, value, body)
        | pattern1 `|` pattern2
        | dominates(parent_pattern, path_pattern, child_pattern)
        | FunctionPattern(params, body)
</pre></div>
</div>
<p>The above language then provides a matching interface with both can select sub-graphs as well as verify that the graph does match the pattern.</p>
<div class="section" id="expression-pattern">
<h3>Expression Pattern<a class="headerlink" href="#expression-pattern" title="永久链接至标题">¶</a></h3>
<p>Match a literal expression.</p>
</div>
<div class="section" id="wildcard">
<h3>Wildcard<a class="headerlink" href="#wildcard" title="永久链接至标题">¶</a></h3>
<p>Match any expression.</p>
</div>
<div class="section" id="type-pattern">
<h3>Type Pattern<a class="headerlink" href="#type-pattern" title="永久链接至标题">¶</a></h3>
<p>Check that the expression matched by the nested pattern has a particular type.</p>
</div>
<div class="section" id="dtype-pattern">
<h3>DType Pattern<a class="headerlink" href="#dtype-pattern" title="永久链接至标题">¶</a></h3>
<p>Check that the expression matched by the nested pattern has a particular data type.</p>
</div>
<div class="section" id="shape-pattern">
<h3>Shape Pattern<a class="headerlink" href="#shape-pattern" title="永久链接至标题">¶</a></h3>
<p>Check that the expression matched by the nested pattern has a particular output shape.</p>
</div>
<div class="section" id="attribute-pattern">
<h3>Attribute Pattern<a class="headerlink" href="#attribute-pattern" title="永久链接至标题">¶</a></h3>
<p>Check that the operator matched by the pattern has an attribute with a particular value.</p>
</div>
<div class="section" id="variable-pattern">
<h3>Variable Pattern<a class="headerlink" href="#variable-pattern" title="永久链接至标题">¶</a></h3>
<p>Check that the expression is a relay Variable, and optional provide a name to match to the Variable name.</p>
</div>
<div class="section" id="alternate">
<h3>Alternate<a class="headerlink" href="#alternate" title="永久链接至标题">¶</a></h3>
<p>Either match the first pattern or the second pattern.</p>
</div>
<div class="section" id="domination">
<h3>Domination<a class="headerlink" href="#domination" title="永久链接至标题">¶</a></h3>
<p>Match child pattern, find a match for the parent pattern, insuring that the child ultimately dominates the parent (i.e., no nodes outside the pattern use outputs of the parent), and that ever node between the child and the pattern matches the path pattern.</p>
</div>
<div class="section" id="function-pattern">
<h3>Function Pattern<a class="headerlink" href="#function-pattern" title="永久链接至标题">¶</a></h3>
<p>Match a Function with a body and parameters</p>
</div>
<div class="section" id="if-pattern">
<h3>If Pattern<a class="headerlink" href="#if-pattern" title="永久链接至标题">¶</a></h3>
<p>Match an If with condition, true branch, and false branch</p>
</div>
<div class="section" id="let-pattern">
<h3>Let Pattern<a class="headerlink" href="#let-pattern" title="永久链接至标题">¶</a></h3>
<p>Match a Let with a variable, value, and body</p>
</div>
</div>
<div class="section" id="applications">
<h2>Applications<a class="headerlink" href="#applications" title="永久链接至标题">¶</a></h2>
<p>The pattern language provides not only the pattern matching but also pattern processing.
Here we introduce two pattern processing approaches and provide some examples.</p>
<div class="section" id="pattern-rewriting">
<h3>Pattern Rewriting<a class="headerlink" href="#pattern-rewriting" title="永久链接至标题">¶</a></h3>
<p>If you would like to replace the matched pattern with another subgraph, you can leverage
the <code class="docutils literal notranslate"><span class="pre">rewrite</span></code> transformation. Here is an example of rewriting a series of arithmetic operators
with a single batch_norm op. The constructor parameter <code class="docutils literal notranslate"><span class="pre">require_type</span></code> indicates whether InferType
is required to be run before the callback.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">BatchnormCallback</span><span class="p">(</span><span class="n">DFPatternCallback</span><span class="p">):</span>
    <span class="c1"># A callback class to rewrite the matched pattern to a batch_norm op.</span>
    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">require_type</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">require_type</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">mean</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">beta</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">gamma</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">eps</span> <span class="o">=</span> <span class="n">wildcard</span><span class="p">()</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">pattern</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">gamma</span> <span class="o">*</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">mean</span><span class="p">)</span><span class="o">/</span><span class="n">is_op</span><span class="p">(</span><span class="s2">&quot;sqrt&quot;</span><span class="p">)(</span><span class="bp">self</span><span class="o">.</span><span class="n">var</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">eps</span><span class="p">)</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">beta</span>

    <span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">pre</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">node_map</span><span class="p">):</span>
        <span class="n">x</span> <span class="o">=</span> <span class="n">node_map</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">x</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">var</span> <span class="o">=</span> <span class="n">node_map</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">var</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">mean</span> <span class="o">=</span> <span class="n">node_map</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">mean</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">beta</span> <span class="o">=</span> <span class="n">node_map</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">beta</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">gamma</span> <span class="o">=</span> <span class="n">node_map</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">gamma</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">eps</span> <span class="o">=</span> <span class="n">node_map</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">eps</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">return</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">batch_norm</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">gamma</span><span class="p">,</span> <span class="n">beta</span><span class="p">,</span> <span class="n">mean</span><span class="p">,</span> <span class="n">var</span><span class="p">,</span> <span class="n">epsilon</span> <span class="o">=</span> <span class="n">eps</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">numpy</span><span class="p">()</span><span class="o">.</span><span class="n">item</span><span class="p">())[</span><span class="mi">0</span><span class="p">]</span>

    <span class="c1"># A graph of arithmetic operators that are functional equivalent to batch_norm.</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">)</span>
    <span class="n">var</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;var&#39;</span><span class="p">)</span>
    <span class="n">mean</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;mean&#39;</span><span class="p">)</span>
    <span class="n">beta</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;beta&#39;</span><span class="p">)</span>
    <span class="n">gamma</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;gamma&#39;</span><span class="p">)</span>
    <span class="n">BN</span> <span class="o">=</span> <span class="n">gamma</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="n">mean</span><span class="p">)</span><span class="o">/</span><span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">var</span> <span class="o">+</span> <span class="n">relay</span><span class="o">.</span><span class="n">const</span><span class="p">(</span><span class="mf">1e-5</span><span class="p">))</span> <span class="o">+</span> <span class="n">beta</span>

    <span class="kn">from</span> <span class="nn">tvm.relay.dataflow_pattern</span> <span class="kn">import</span> <span class="n">rewrite</span>
    <span class="n">out</span> <span class="o">=</span> <span class="n">rewrite</span><span class="p">(</span><span class="n">BatchnormCallback</span><span class="p">(),</span> <span class="n">BN</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">tvm</span><span class="o">.</span><span class="n">ir</span><span class="o">.</span><span class="n">structural_equal</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">batch_norm</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">gamma</span><span class="p">,</span> <span class="n">beta</span><span class="p">,</span> <span class="n">mean</span><span class="p">,</span> <span class="n">var</span><span class="p">,</span> <span class="n">epsilon</span> <span class="o">=</span> <span class="mf">1e-5</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span>
</pre></div>
</div>
<p>The function <code class="docutils literal notranslate"><span class="pre">def</span> <span class="pre">callback(self,</span> <span class="pre">pre,</span> <span class="pre">post,</span> <span class="pre">node_map)</span></code> will be invoked when the rewriter matches
<code class="docutils literal notranslate"><span class="pre">self.pattern</span></code>. <code class="docutils literal notranslate"><span class="pre">node_map</span></code> is a dictionary mapping from pattern nodes to matched nodes in the graph.</p>
<p>The callback function will be invoked recursively on the returned pattern until the pattern stops changing. As a result, if <code class="docutils literal notranslate"><span class="pre">self.pattern</span></code> matches any part of the graph that the callback returned, the rewriter will run in a loop. If you want to avoid multiple rewrites, you can pass a <code class="docutils literal notranslate"><span class="pre">rewrite_once=True</span></code> parameter to the constructor.</p>
</div>
<div class="section" id="pattern-partitioning">
<h3>Pattern Partitioning<a class="headerlink" href="#pattern-partitioning" title="永久链接至标题">¶</a></h3>
<p>If you would like to perform a more complex processing for matched subgraphs and you are not
satisfied with <code class="docutils literal notranslate"><span class="pre">rewrite</span></code>, you may consider partitioning the matched subgraphs to a separate
Relay function and perform other processes to the function. Here we use <code class="docutils literal notranslate"><span class="pre">pattern.partition</span></code>
to create a new Relay function for each matched subgraph. The functionality is similar to
the op fusion pass in TVM:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># A pattern matching conv2d+relu.</span>
<span class="n">pattern</span> <span class="o">=</span> <span class="n">is_op</span><span class="p">(</span><span class="s2">&quot;nn.relu&quot;</span><span class="p">)(</span><span class="n">is_op</span><span class="p">(</span><span class="s2">&quot;nn.conv2d&quot;</span><span class="p">)(</span><span class="n">wildcard</span><span class="p">(),</span> <span class="n">wildcard</span><span class="p">()))</span>

<span class="c1"># A graph.</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;input&#39;</span><span class="p">)</span>
<span class="n">w</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">var</span><span class="p">(</span><span class="s1">&#39;weight&#39;</span><span class="p">)</span>
<span class="n">conv2d</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">conv2d</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">w</span><span class="p">)</span>
<span class="n">relu</span> <span class="o">=</span> <span class="n">relay</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">nn</span><span class="o">.</span><span class="n">relu</span><span class="p">(</span><span class="n">conv2d</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s1">&#39;relu&#39;</span><span class="p">)</span>
<span class="c1"># free_var %x: Tensor[(1, 3, 224, 224), float32]</span>
<span class="c1"># free_var %w: Tensor[(3, 3, 3, 3), float32]</span>
<span class="c1"># %0 = nn.conv2d(%x, %w, padding=[0, 0, 0, 0]) /* ty=Tensor[(1, 3, 222, 222), float32] */;</span>
<span class="c1"># free_var %b: Tensor[(3), float32]</span>
<span class="c1"># nn.bias_add(%0, %b) /* ty=Tensor[(1, 3, 222, 222), float32] */</span>

<span class="c1"># After partition.</span>
<span class="k">print</span><span class="p">(</span><span class="n">pattern</span><span class="o">.</span><span class="n">partition</span><span class="p">(</span><span class="n">relu</span><span class="p">))</span>
<span class="c1"># free_var %x: Tensor[(1, 3, 224, 224), float32]</span>
<span class="c1"># free_var %w: Tensor[(3, 3, 3, 3), float32]</span>
<span class="c1"># free_var %b: Tensor[(3), float32]</span>
<span class="c1"># %1 = fn (%FunctionVar_0_0, %FunctionVar_0_1,</span>
<span class="c1">#          %FunctionVar_0_2, PartitionedFromPattern=&quot;nn.conv2d_nn.bias_add_&quot;) {</span>
<span class="c1">#   %0 = nn.conv2d(%FunctionVar_0_0, %FunctionVar_0_1, padding=[0, 0, 0, 0]);</span>
<span class="c1">#   nn.bias_add(%0, %FunctionVar_0_2)</span>
<span class="c1"># };</span>
<span class="c1"># %1(%x, %w, %b)</span>
</pre></div>
</div>
<p>Note that you can also specify the attributes for the created functions:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">print</span><span class="p">(</span><span class="n">pattern</span><span class="o">.</span><span class="n">partition</span><span class="p">(</span><span class="n">relu</span><span class="p">,</span> <span class="p">{</span><span class="s1">&#39;Composite&#39;</span><span class="p">:</span> <span class="s1">&#39;one_layer&#39;</span><span class="p">}))</span>
<span class="c1"># free_var %x: Tensor[(1, 3, 224, 224), float32]</span>
<span class="c1"># free_var %w: Tensor[(3, 3, 3, 3), float32]</span>
<span class="c1"># free_var %b: Tensor[(3), float32]</span>
<span class="c1"># %1 = fn (%FunctionVar_0_0, %FunctionVar_0_1,</span>
<span class="c1">#          %FunctionVar_0_2, Composite=&quot;one_layer&quot;,</span>
<span class="c1">#                            PartitionedFromPattern=&quot;nn.conv2d_nn.bias_add_&quot;) {</span>
<span class="c1">#   %0 = nn.conv2d(%FunctionVar_0_0, %FunctionVar_0_1, padding=[0, 0, 0, 0]);</span>
<span class="c1">#   nn.bias_add(%0, %FunctionVar_0_2)</span>
<span class="c1"># };</span>
<span class="c1"># %1(%x, %w, %b)</span>
</pre></div>
</div>
<p>If you need a customized checking function that cannot be specified using pattern language,
you can specify <code class="docutils literal notranslate"><span class="pre">check</span></code> function when partitioning. The following example demonstrates a
case that checks input data layout of a subgraph:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">check</span><span class="p">(</span><span class="n">pre</span><span class="p">):</span>
    <span class="n">conv</span> <span class="o">=</span> <span class="n">pre</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">conv</span><span class="o">.</span><span class="n">attrs</span><span class="o">.</span><span class="n">data_layout</span> <span class="o">==</span> <span class="s2">&quot;NCHW&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">bool</span><span class="p">(</span><span class="n">conv</span><span class="o">.</span><span class="n">checked_type</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span>

<span class="n">pattern</span><span class="o">.</span><span class="n">partition</span><span class="p">(</span><span class="n">relu</span><span class="p">,</span> <span class="n">check</span><span class="o">=</span><span class="n">check</span><span class="p">)</span>
</pre></div>
</div>
<p>In this example, we check if the first argument of the matched subgraph (i.e., <code class="docutils literal notranslate"><span class="pre">pre.args[0]</span></code>)
has data layout “NCHW” and if its batch size is 1. This feature is useful if the conditions
of matching a pattern cannot be verified by analyzing the pattern itself.</p>
</div>
</div>
</div>


           </div>
           
          </div>
          

<footer>

    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="hybrid_script.html" class="btn btn-neutral float-right" title="Hybrid Frontend Language Reference" accesskey="n" rel="next">下一个 <span class="fa fa-arrow-circle-right"></span></a>
      
      
        <a href="relay_op.html" class="btn btn-neutral float-left" title="Relay 基础张量算子" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> 上一个</a>
      
    </div>

<div id="button" class="backtop"><img src="../../_static//img/right.svg" alt="backtop"/> </div>
<section class="footerSec">
    <div class="footerHeader">
      <ul class="d-flex align-md-items-center justify-content-between flex-column flex-md-row">
        <li class="copywrite d-flex align-items-center">
          <h5 id="copy-right-info">© 2020 Apache Software Foundation | All right reserved</h5>
        </li>
      </ul>

    </div>

    <ul>
      <li class="footernote">Copyright © 2020 The Apache Software Foundation. Apache TVM, Apache, the Apache feather, and the Apache TVM project logo are either trademarks or registered trademarks of the Apache Software Foundation.</li>
    </ul>

</section>
</footer>
        </div>
      </div>

    </section>

  </div>
  

    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

  </body>
  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script>

  
  
    
    <!-- Theme Analytics -->
    <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-75982049-2', 'auto');
    ga('send', 'pageview');
    </script>

    
   

</body>
</html>